home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-12-06 | 6.6 KB | 210 lines | [TEXT/MPS ] |
- //////////////////////////////////////////////////////////////////////////
- // UniqueRGBValues.c: A function that returns the number of unique
- // colors found in a direct RGB formatted image.
- // _______________________________________________________________________
- // Copyright © 1992
- // Thomas W. Pinkerton.
- // All rights reserved.
- //
- //
- // Solution for the November/December 1992
- // MacTutor Programmers' Challenge
- //
- // Author: Tom Pinkerton
- // 426 1/2 Ridge Road
- // Wilmette, IL. 60091
- //
- // Phone: (708) 251-6733
- // FAX: (708) 251-6737
- //
- // AppleLink: TPINKERTON
- // A Online: TomPnk
- // CompuServe: [71041,144]
- //
- // _______________________________________________________________________
- //////////////////////////////////////////////////////////////////////////
-
- unsigned long UniqueRGBValues(Ptr baseAddress, short numRows, short numCols);
-
- //////////////////////////////////////////////////////////////////////////
-
- unsigned long UniqueRGBValues(Ptr baseAddress,
- short numRows,
- short numCols)
-
- {
- Handle sBuffers = nil;
- long sUniquePixels = 0;
-
- //• Allocate memory for the data structures.
- //• We will need:
- //•
- //• 256 x 4 bytes for the unique blue value table.
- //• 256 x 256 x 8 bytes for the Red/Green intersection grid.
- //• numRows x numCols x 4 bytes for the master blue list.
- //•
- sBuffers = NewHandle((((long)numRows * (long)numCols) * 4L) + 525312);
- if (sBuffers != nil) {
-
- //• Setup pointers to the data structures.
- long* sBluListPtr = (long*)((char*)*sBuffers + 0);
- long* sRGTablePtr = (long*)((char*)*sBuffers + 1024);
- long* sRGLinksPtr = (long*)((char*)*sBuffers + 525312);
- long* sRGBase = nil;
-
- //• Initialize the Red/Green intersection grid and
- //• the master Blue list with -1's.
- {
- register long* sInitPtr;
- register long i;
-
- //• A -1 in this table means that the blue value for
- //• a particular Red/Green combination is not yet found.
- sInitPtr = sBluListPtr;
- i = 64;
- while (i--) {
- sInitPtr[3] =
- sInitPtr[2] =
- sInitPtr[1] =
- sInitPtr[0] = -1;
- sInitPtr += 4;
- }
-
- //• Only the blue list link need be initialized (first
- //• of two longs) for each element. A -1 means that a
- //• unique Red/Green pair represented by this intersection
- //• has not yet been found.
- sInitPtr = sRGTablePtr;
- i = 4096;
- while (i--) {
- sInitPtr[30] =
- sInitPtr[28] =
- sInitPtr[26] =
- sInitPtr[24] =
- sInitPtr[22] =
- sInitPtr[20] =
- sInitPtr[18] =
- sInitPtr[16] =
- sInitPtr[14] =
- sInitPtr[12] =
- sInitPtr[10] =
- sInitPtr[ 8] =
- sInitPtr[ 6] =
- sInitPtr[ 4] =
- sInitPtr[ 2] =
- sInitPtr[ 0] = -1;
- sInitPtr += 32;
- }
- }
-
- //• Scan the image to create a linked list of blue values at
- //• each unique Red/Green intersection. Each element in the
- //• Red/Green intersection grid consists of the first link
- //• of that intersection's blue list (initially -1) and a link
- //• to the next Red/Green intersection which contains a blue
- //• list. Whereas the Red/Green link is a pointer to the next
- //• Red/Green intersection, a blue list link holds an array index
- //• in its low order 3 bytes and an actual blue value in its
- //• high order byte. The blue link index refers to an element
- //• in the master blue list. Each master blue list element then
- //• points to the next blue value link within a specific blue
- //• list or terminates the list with a -1 value.
- {
- register unsigned char* sPixelsPtr = (unsigned char*)baseAddress;
- register long* sRGPtr;
- register long* sLinkPtr = sRGLinksPtr;
- register long sLinkIndex = 0;
- register long sNumPixels = (long)numRows * (long)numCols;
-
- //• For each pixel in the image, do the following.
- while (sNumPixels--) {
-
- //• Concatenate the red and green values to create
- //• an offset used to point at the unique Red/Green
- //• element in the Red/Green intersection grid.
- sRGPtr = sRGTablePtr + ((((long)sPixelsPtr[1] << 8) |
- (long)sPixelsPtr[2]) << 1);
-
- //• If this is the first pixel with this particular
- //• Red/Green combination, then add the Red/Green
- //• intersection to the Red/Green linked list.
- if (sRGPtr[0] == -1) {
- sRGPtr[1] = (long)sRGBase;
- sRGBase = sRGPtr;
- }
-
- //• Create a new blue link with the pixel's blue value
- //• and add it to Red/Green intersection's blue list.
- *sLinkPtr = sRGPtr[0];
- sRGPtr[0] = sLinkIndex | ((long)sPixelsPtr[3] << 24);
-
- //• Increment stuff for the next go 'round.
- ++sLinkPtr;
- ++sLinkIndex;
- sPixelsPtr += 4;
- }
- }
-
- //• For each list of blue values at a unique Red/Green
- //• intersection, determine the number of unique blue
- //• values in that list. This calculates the number of
- //• unique colors that have the same Red and Green values.
- //• Accumulating the number of unique colors at every
- //• Red/Green intersection gives us the total number of
- //• unique colors.
- {
- register long* sRGPtr = sRGBase;
- register long* sBlueBase = nil;
- register long* sBluePtr;
- register long sLinkIndex;
-
- //• For each Red/Green intersection found above,
- //• do the following.
- while (sRGPtr != nil) {
-
- //• Walk the list of blue values for this Red/Green pair.
- //• For each one, do the following.
- sLinkIndex = sRGPtr[0];
- while (sLinkIndex != -1) {
-
- //• Create a pointer to the unique blue value element.
- sBluePtr = sBluListPtr + ((unsigned long)sLinkIndex >> 24);
-
- //• A -1 here means that the unique R/G and B color has
- //• not yet been counted. Therefore, mark the fact that
- //• it has been counted by adding the element to a linked
- //• list and incrementing the unique color count. The
- //• blue value linked list is used later to quickly reset
- //• itself.
- if (*sBluePtr == -1) {
- *sBluePtr = (long)sBlueBase;
- sBlueBase = sBluePtr;
- ++sUniquePixels;
- }
-
- //• Get the next blue list link in the blue list.
- sLinkIndex = sRGLinksPtr[sLinkIndex & 0x00FFFFFF];
- }
-
- //• Reset the blue count list by walking its links and
- //• replacing them again with -1's.
- sBluePtr = sBlueBase;
- while (sBluePtr != nil) {
- sBlueBase = (long*)*sBluePtr;
- *sBluePtr = -1;
- sBluePtr = sBlueBase;
- }
- sBlueBase = nil;
-
- //• Get next Red/Green intersection.
- sRGPtr = (long*)sRGPtr[1];
- }
- }
-
- DisposHandle(sBuffers);
- }
- return(sUniquePixels);
- }
-
- //////////////////////////////////////////////////////////////////////////
-